package com.niiwoo.civet.account.service.local.check;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.alibaba.dubbo.config.annotation.Reference;
import com.niiwoo.civet.trade.dto.common.LendOrderDetailDTO;
import com.niiwoo.civet.trade.service.lend.ProjectLendDetailDubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.github.pagehelper.PageHelper;
import com.niiwoo.civet.account.dao.entity.AccountCheckingBatchLendOrder;
import com.niiwoo.civet.account.dao.entity.AccountCheckingException;
import com.niiwoo.civet.account.dao.entity.AccountCheckingTransStat;
import com.niiwoo.civet.account.dao.mapper.AccountCheckingBatchLendOrderMapper;
import com.niiwoo.civet.account.dao.mapper.AccountCheckingTransStatMapperExt;
import com.niiwoo.civet.account.service.local.check.job.api.CheckDetailService;
import com.niiwoo.civet.account.service.local.check.job.enums.CheckExceptionStatusEnum;
import com.niiwoo.civet.account.service.local.check.job.enums.CheckResultEnum;
import com.niiwoo.civet.account.service.local.check.job.enums.HandleTypeEnum;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class AccountCheckingTransStatService implements CheckDetailService<AccountCheckingTransStat> {

	@Autowired
	private AccountCheckingTransStatMapperExt accountCheckingTransStatMapperExt;
	
	@Autowired
	private AccountCheckingBatchLendOrderMapper accountCheckingBatchLendOrderMapper;

	@Reference(version = "1.0.0")
	private ProjectLendDetailDubboService projectLendDetailDubboService;

	public List<AccountCheckingTransStat> load(Long checkRecordId, int page, int pageSize) {
		// shardingjdbc 强制走主库
		if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
				
		log.debug("is matster route only : {}", HintManagerHolder.isMasterRouteOnly());
		
		PageHelper.startPage(page, pageSize);
		AccountCheckingTransStat condition = new AccountCheckingTransStat();
		condition.setCheckingRecordId(checkRecordId);
		return accountCheckingTransStatMapperExt.selectBy(condition);
	}

	/**
	 * 见上海银行对账文件格式说明V1.12.pdf 2.4 交易 文件
	 * 【业务类型】：03投标(放款)
	 * 异常类型: 1银行有记录，平台无记录，2银行无记录，平台有记录，3银行与平台记录存在差异
	 * 所属对账文件: 2交易文件
	 *
	 * 比对流程：
	 * 1. 根据平台流水号查找对应表获取数据；
	 * 2. 比对金额(amount)和
	 * @param transation
	 * @param checkDate 对账日期
	 * @return
	 */
	public AccountCheckingException check(AccountCheckingTransStat transation, String checkDate) {
		if (transation == null)
			return null;

		AccountCheckingException exp = null;

		switch (transation.getBusinessType()) {
		case 3:
			exp = checkBatchInvestNew(transation, checkDate);
			break;
		default:
			exp = getPlatformNoRecordException(transation, checkDate);
			break;
		}

		return exp;
	}

	/**
	 * 老版：为了支持线上数据，运行一段时间之后，本方法需要删除
	 * @param transation
	 * @param checkDate
	 * @return
	 */
	private AccountCheckingException checkBatchInvest(AccountCheckingTransStat transation, String checkDate) {
		List<AccountCheckingBatchLendOrder> list = accountCheckingBatchLendOrderMapper.selectByRequestNo(transation.getPlatformRequestNo());
		if (list == null || list.isEmpty()) {
			return getPlatformNoRecordException(transation, checkDate);
		}
		
		AccountCheckingBatchLendOrder batchLendOrder = list.get(0);
		
		StringBuffer buf = new StringBuffer();
		boolean isTrue = true;
		if (transation.getAmount().compareTo(batchLendOrder.getAmountTotal()) != 0) {
			isTrue = false;
			buf.append("总金额不等；");
		}
		
		if (!transation.getRecordCount().equals(batchLendOrder.getNumTotal())) {
			isTrue = false;
			buf.append("总笔数不等；");
		}
		
		if (!isTrue) {
			AccountCheckingException exp = new AccountCheckingException();
			exp.setBillDate(checkDate);
			exp.setBusinessType(transation.getBusinessType());
			exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex()); // 1银行有记录，平台无记录
			exp.setCreateTime(new Date());
			exp.setCheckingRecordId(transation.getCheckingRecordId());
			exp.setCheckingDetailId(transation.getId());
			exp.setPlatformRecordId(batchLendOrder.getId());
			exp.setCheckingType((byte) 2); // 2交易文件
			exp.setDescription(buf.toString());
			exp.setStatus(CheckExceptionStatusEnum.UNCONFIRM.getCode());
			exp.setOrderNo(batchLendOrder.getRequestNo());

			return exp;
		}

		return null;
	}

	private AccountCheckingException checkBatchInvestNew(AccountCheckingTransStat transation, String checkDate) {
		AccountCheckingException accountCheckingException = checkBatchInvest(transation,checkDate);
		List<String> errors = new ArrayList<String>();
		if( null != accountCheckingException && accountCheckingException.getHandleType().equals(HandleTypeEnum.BACK_ONLY.getIndex()) ){
			LendOrderDetailDTO lendOrderDetailDTO = projectLendDetailDubboService.queryLendOrderDetailByRequestNO(transation.getPlatformRequestNo());
            Boolean recordIsTrue = Boolean.TRUE;
			if( null == lendOrderDetailDTO ){
            	 return submit(transation,accountCheckingException,lendOrderDetailDTO,errors,checkDate);
			}
			if( transation.getAmount().compareTo(lendOrderDetailDTO.getAmountTotal()) != 0 ){

				recordIsTrue = Boolean.FALSE;
				accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
				errors.add(CheckResultEnum.LOAN_AMOUNT_NOT_EQUAL.getName());
				accountCheckingException.setPlatformRecordId(lendOrderDetailDTO.getId());
			}
			if (!transation.getRecordCount().equals(lendOrderDetailDTO.getNumTotal())) {
				recordIsTrue = Boolean.FALSE;
				accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
				errors.add(CheckResultEnum.LOAN_COUNT_NOT_EQUAL.getName());
				accountCheckingException.setPlatformRecordId(lendOrderDetailDTO.getId());
			}
			if( recordIsTrue){
				accountCheckingException = null;
				errors.clear();
			}
		}
		return accountCheckingException;
	}

	private AccountCheckingException getPlatformNoRecordException(AccountCheckingTransStat transation,
			String checkDate) {
		AccountCheckingException exp = new AccountCheckingException();
		exp.setBillDate(checkDate);
		exp.setBusinessType(transation.getBusinessType());
		exp.setHandleType(HandleTypeEnum.BACK_ONLY.getIndex()); // 1银行有记录，平台无记录
		exp.setCreateTime(new Date());
		exp.setCheckingRecordId(transation.getCheckingRecordId());
		exp.setCheckingDetailId(transation.getId());
		exp.setCheckingType((byte) 2); // 2交易文件
		exp.setDescription(CheckResultEnum.NO_RECORD.getName());
		exp.setStatus(CheckExceptionStatusEnum.UNCONFIRM.getCode());
		exp.setOrderNo(transation.getPlatformRequestNo());

		return exp;
	}

	public void deleteCheckRecord(Long checkingRecordId) {
		accountCheckingTransStatMapperExt.deleteIncompleteRecord(checkingRecordId);
	}

	public void batchUpdateCheckDetailStatus(Long checkingRecordId, Byte status) {
		accountCheckingTransStatMapperExt.batchUpdateCheckDetailStatus(checkingRecordId, status);
	}

	@Override
	public void deleteAllCheckSuccessBankOrder(Long checkingRecordId) {
		accountCheckingTransStatMapperExt.deleteAllCheckSuccessBankOrder(checkingRecordId);
	}

	private AccountCheckingException submit(AccountCheckingTransStat accountCheckingTransStat,
											AccountCheckingException accountCheckingException, LendOrderDetailDTO lendOrderDetailDTO, List<String> errors,
											String checkDate) {
		if (null != errors && errors.size() > 0) {
			accountCheckingException.setStatus(CheckExceptionStatusEnum.UNCONFIRM.getCode());
			accountCheckingException.setBusinessType(accountCheckingTransStat.getBusinessType());
			accountCheckingException.setOrderNo(accountCheckingTransStat.getPlatformRequestNo());
			accountCheckingException.setCheckingType((byte) 2);
			accountCheckingException.setCheckingRecordId(accountCheckingTransStat.getCheckingRecordId());
			accountCheckingException.setCheckingDetailId(accountCheckingTransStat.getId());
			accountCheckingException.setPlatformRecordId(lendOrderDetailDTO == null ? null : lendOrderDetailDTO.getId());
			accountCheckingException.setCreateTime(new Date());
			accountCheckingException.setBillDate(checkDate);
			accountCheckingException.setDescription(errors.toString());
			return accountCheckingException;
		}
		return null;
	}
}
